#include "moduserdb.h"
#include "pg_common.h"

int main(int argc, char **argv) {

    struct users *usert;
   char sql[512],pass[9];
        CONNECTION_DB conn;
   PGresult *result;
   int c, newpass=0;

   usert = (struct users *) malloc(sizeof(struct users));
   usert->user=NULL;
   usert->home=NULL;
   usert->group=NULL;
   usert->name=NULL;
   usert->comment=NULL;
   usert->shell=NULL;
   usert->matriculation=NULL;
   usert->grade=NULL;
   usert->blocked=-1;

   if(getuid() != 0) {
      printf("Somente o root pode executar esse comando\n");
      exit(0);
   }

   if(argc < 2) {
      print_help();
      exit(0);
   }

   while ( (c=getopt (argc, argv, "m:o:b:g:d:n:c:s:rh")) != -1 ) {

      switch (c) {

         case 'g':
            usert->group = strdup(optarg);
         break;

         case 'm':
	    usert->matriculation = strdup(optarg);
	 break;
         
         case 'o':
	   usert->grade = strdup(optarg);
	 break;

         case 'b':
	   usert->blocked = atoi(strdup(optarg));
         break;

         case 'd':
            usert->home = strdup(optarg);
         break;

         case 'r':
            newpass=1;
         break;

         case 'n':
            usert->name = strdup(optarg);
         break;

         case 's':
            usert->shell = strdup(optarg);
         break;

         case 'h':
           print_help();
      exit(0);
         break;

         case 'c':
            usert->comment = strdup(optarg);
         break;

         case '?':
         break;

      }

   }

   if(optind < argc) {
                   usert->user = strdup(argv[optind++]);
   } else {
      printf("\n     >> Usuario nao especificado << \n\n");
      print_help();
      exit(0);
   }

   conn = init_db(DB_ARQ_CONF);
   if( PQstatus(conn->pgconn) != CONNECTION_OK ) {
      printf("Falha na conexao\n");
      exit(0);
   }

   sprintf(sql, "SELECT * FROM user_sys WHERE login='%s'", usert->user);
   result = PQexec(conn->pgconn, sql);
   if(PQntuples(result)==0) {

      printf("Usuario nao existe\n");
      free_db(conn);
      exit(0);

   } else {
      usert->user_id=atoi(PQgetvalue(result,0,0));
      if(usert->name == NULL) usert->name = strdup(PQgetvalue(result,0,3));
      if(usert->home == NULL) usert->home = strdup(PQgetvalue(result,0,4));
      if(usert->shell == NULL) usert->shell = strdup(PQgetvalue(result,0,5));
      if(usert->comment == NULL) usert->comment = strdup(PQgetvalue(result,0,6));
      usert->user_id = atoi(PQgetvalue(result, 0, 0));
      usert->group_id = atoi(PQgetvalue(result,0,1));
   }

   sprintf(sql, "SELECT * FROM user_extended WHERE user_id=%d",usert->user_id);
   result = PQexec(conn->pgconn,sql);
   if(PQntuples(result)==0) {

      printf("Usuario nao existe\n");
      free_db(conn);
      exit(0);

   } else {

     if(usert->matriculation==NULL) usert->matriculation = strdup(PQgetvalue(result,0,1));
     if(usert->grade==NULL) usert->grade = strdup(PQgetvalue(result,0,3));
     if(usert->blocked>1) usert->blocked=1;
     else if(usert->blocked==-1) usert->blocked = atoi(PQgetvalue(result,0,5));
  								 
   }

   if(usert->group != NULL) {

      sprintf(sql, "SELECT group_id FROM group_sys WHERE name='%s'", usert->group);
      result = PQexec(conn->pgconn, sql);
      if(PQntuples(result)==0) {
         printf("Grupo '%s' nao existe\n", usert->group);
         free_db(conn);
         exit(0);
      } else {
         usert->group_id = atoi(PQgetvalue(result,0,0));
      }

   } 
   //else {
   // usert->group_id = atoi(PQgetvalue(result, 0, 0));
   //}

   if(newpass==1) {

      gen_pass(pass);
      char *md5 = encrypt_password(pass);
      sprintf(sql, "UPDATE user_shadow SET passwd='%s' WHERE user_id='%d'", md5, usert->user_id);
      PQexec(conn->pgconn, sql);
      printf("Nova senha: %s\n", pass);

   }

   sprintf(sql, "UPDATE user_sys SET nome='%s', home='%s', shell='%s', comment='%s', group_id='%d' WHERE login='%s';", usert->name, usert->home, usert->shell, usert->comment, usert->group_id, usert->user);
   PQexec(conn->pgconn, sql);

   if(strlen(PQerrorMessage(conn->pgconn)) > 2)
      printf("Erro ao adicionar usuario %s: %s\n", usert->user, PQerrorMessage(conn->pgconn));

   sprintf(sql, "UPDATE user_extended SET matriculation='%s', grade='%s', blocked=%d WHERE user_id=%d;", usert->matriculation, usert->grade, usert->blocked, usert->user_id);
   PQexec(conn->pgconn, sql);

   if(strlen(PQerrorMessage(conn->pgconn)) > 2)
      printf("Erro ao fazer update de user_extended %s: %s\n", 
	     usert->user, PQerrorMessage(conn->pgconn));


   free(conn);
   return 0;

}

void print_help() {

   printf("Uso correto: moduserdb [options] LOGIN\n\n");
   printf("Opcoes:\n");
   printf("  -g      Grupo padrao do usuario (padrao: bcc)\n");
   printf("  -m      Matricula (padrao:NULL)\n");
   printf("  -o      Curso (padrao:NULL)\n");
   printf("  -b      Bloqueia usuario (padra: desbloqueado)\n");
   printf("  -d      Home do usuario (padrao: /home/bcc/LOGIN)\n");
   printf("  -s      Binario padrao de execucao ao login (padrao: /bin/bash)\n");
   printf("  -n      Nome do usuario (ex: -n \"Nome do cidadao\")\n");
   printf("  -f      Adiciona sem pergunta se informacoes estao corretas\n");
   printf("  -r      Gera novamente uma senha aleatoria para usuario\n");
   printf("  -h      Mostra essa ajuda\n");
   printf("\nSECURE DB USERS SYSTEM MANAGEMENT\n");

}

void gen_pass(char *pass) {

        FILE *fp;
        int num,read=1,i=0;

        fp = fopen("/dev/urandom", "r");
        if(fp==NULL) printf("erro\n");

        while(read==1) {

           num = (int) fgetc(fp);
           if( (num > 64 && num < 91) || (num > 96 && num < 123) ) {
              pass[i]=num;
              if(i==8) read=0;
              i++;
           }
        }
        pass[i]='\0';

}

char * encrypt_password(const char *pass) {

   char *s = NULL;
   char *buf;
   int buf_size;
   unsigned int i;
   MHASH handle;
   unsigned char *hash;

   handle = mhash_init(MHASH_SHA1);
   if(handle == MHASH_FAILED) {
      printf("Problema no mhash\n");
      exit(0);
   } else {
      mhash(handle, pass, strlen(pass));
      hash = mhash_end(handle);
      if (hash != NULL) {
         buf_size = (mhash_get_block_size(MHASH_SHA1) * 2)+1;
         buf = (char *)malloc(buf_size);
         bzero(buf, buf_size);

         for(i = 0; i < mhash_get_block_size(MHASH_SHA1); i++)
               sprintf(&buf[i * 2], "%.2x", hash[i]);

         free(hash);
         s = buf;
      } else {
         s = strdup("!");
      }
   }

   return s;

}
